/**
 * Server-side Axios API Fixture System
 *
 * This module uses Axios interceptors to record and replay HTTP responses for server-side
 * API calls made by Express controllers. It enables deterministic testing without requiring
 * live API credentials or network access.
 *
 * How it works:
 * - RECORD MODE (API_MODE=record): Axios response interceptor captures successful responses
 *   and saves JSON data to test/fixtures/ using sanitized URL-based filenames.
 * - REPLAY MODE (API_MODE=replay): Axios request interceptor short-circuits requests by
 *   returning saved fixture data. If fixture exists, it rejects the request with a special
 *   marker (isAxiosFixture:true), which the response error interceptor converts back to a
 *   successful response. Falls back to real axios if fixture is missing (unless
 *   API_STRICT_REPLAY=1, which blocks all non-fixture requests).
 *
 * Installation: This module is automatically installed in test/tools/start-with-memory-db.js
 * before the Express app loads, ensuring all server-side axios calls are intercepted.
 *
 * Fixture keys: Generated by keyFor() helper, which sanitizes URLs (strips sensitive query
 * params like apikey/token) and adds body hashes for POST requests to ensure uniqueness.
 *
 * See also: server-fetch-fixtures.js (same pattern for fetch), fixture-helpers.js (shared utilities)
 */

const fs = require('fs');
const path = require('path');
const axios = require('axios');
const { keyFor } = require('./fixture-helpers');

const FIXTURES_DIR = path.resolve(__dirname, '..', 'fixtures');

function installServerAxiosFixtures({ mode = process.env.API_MODE } = {}) {
  const strict = process.env.API_STRICT_REPLAY === '1';

  if (mode === 'record') {
    axios.interceptors.response.use((response) => {
      try {
        const { config, headers, data } = response;
        const ct = (headers && headers['content-type']) || '';
        if (typeof data === 'object' || ct.toLowerCase().includes('application/json')) {
          const file = path.join(FIXTURES_DIR, keyFor(config.method || 'GET', config.url, config.data));
          fs.writeFileSync(file, typeof data === 'string' ? data : JSON.stringify(data), 'utf8');
        }
      } catch {}
      return response;
    });
  } else if (mode === 'replay') {
    axios.interceptors.request.use((config) => {
      try {
        const file = path.join(FIXTURES_DIR, keyFor(config.method || 'GET', config.url, config.data));
        if (fs.existsSync(file)) {
          const data = JSON.parse(fs.readFileSync(file, 'utf8'));
          console.log(`[fixtures] server replay ${(config.method || 'GET').toUpperCase()} ${config.url}`);
          return Promise.reject({
            isAxiosFixture: true,
            config,
            response: { config, status: 200, statusText: 'OK', headers: { 'content-type': 'application/json' }, data, request: {} },
          });
        }
        if (strict) {
          console.warn(`[fixtures] server strict-replay missing: ${(config.method || 'GET').toUpperCase()} ${config.url} — blocking network`);
          throw new Error(`Strict replay: missing fixture for ${(config.method || 'GET').toUpperCase()} ${config.url}`);
        }
      } catch {}
      return config;
    });

    axios.interceptors.response.use(
      (response) => response,
      (error) => (error?.isAxiosFixture ? Promise.resolve(error.response) : Promise.reject(error)),
    );
  }
}

module.exports = { installServerAxiosFixtures };
